/*
	Copyright (C) 2010 2011 Rémi Thebault

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef __pc_link_h__
#define __pc_link_h__

#include <QObject>
#include <QList>
#include <QString>

#include <procycle/xml_storable.h>


namespace PC {



class Link;
class Task;
class Cycle;



const QString LINK_ELEMENT_NAME = "link";


class Link: public QObject, public XmlStorable {

	Q_OBJECT

public:


	enum Type
	{
		TYPE_FS = 0,		// finish to start
		TYPE_SS,			// start to start
		TYPE_SF,			// ...
		TYPE_FF,
	};

	typedef QList<Link*>::iterator iterator;
	typedef QList<Link*>::const_iterator const_iterator;


	Link(Task* from, Task* to, Type type, int lag=0);

	Link(Cycle* cycle);

	virtual ~Link();



	Cycle* cycle() {
		return m_cycle;
	}



	Task* taskFrom () const {
		return m_taskFrom;
	}
	void setTaskFrom(Task* taskFrom);

	Task* taskTo () const {
		return m_taskTo;
	}
	void setTaskTo(Task* taskTo);

	void registerToTasks();

	Type type() const {
		return m_type;
	}
	void setType(Type type) {
		m_type = type;
	}

	int lag() const {
		return m_lag;
	}
	void setLag(int lag);

	bool isCriticalPath();

	int timeFrom();
	int timeTo();
	int lateTimeFrom();
	int lateTimeTo();


	bool fromStart() {
		return (
			m_type == TYPE_SS ||
			m_type == TYPE_SF
		);
	}

	bool fromFinish() {
		return !fromStart();
	}

	bool toStart() {
		return (
			m_type == TYPE_FS ||
			m_type == TYPE_SS
		);
	}

	bool toFinish() {
		return !toStart();
	}


	virtual QString elementName() const {
		return LINK_ELEMENT_NAME;
	}
	virtual void loadFromElement (const QDomElement& element);
	virtual QDomElement saveToElement (QDomDocument& doc) const;


signals:

	void changed(PC::Link* link);


private:
	Cycle*		m_cycle;

	Task*		m_taskFrom;
	Task*		m_taskTo;
	Type		m_type;
	int			m_lag;


	QString type_to_string () const {
		switch(m_type) {
		case TYPE_FS:
			return "FS";
		case TYPE_SS:
			return "SS";
		case TYPE_SF:
			return "SF";
		case TYPE_FF:
			return "FF";
		}
		return QString();
	}

	Type string_to_type(QString s) const {
		if (s == "FS") {
			return TYPE_FS;
		}
		if (s == "SS") {
			return TYPE_SS;
		}
		if (s == "SF") {
			return TYPE_SF;
		}
		if (s == "FF") {
			return TYPE_FF;
		}
		throw XmlFormatError();
	}
};

}

#endif /* __pc_link_h__ */
